#!/bin/bash

set -e
set -x

bmode=1
cmode=
makeflag=
target=

SRC_PATH=$PWD
IMAGE_PATH=${SRC_PATH}/images
ENGINE_PATH=${SRC_PATH}/openresty-1.27.1.1
ENGINE_INSTALL=$SRC_PATH/install
TRD_PATH=${SRC_PATH}/3rd-party
NEU_PATH=${SRC_PATH}/neusoft
MODSECURITY_PATH=${SRC_PATH}/modsecurity
MODSECURITY_LIB_PATH=${MODSECURITY_PATH}/modsecurity-v3.0.12

export MODSECURITY_INC="$MODSECURITY_LIB_PATH/headers"
export MODSECURITY_LIB="$MODSECURITY_LIB_PATH/src/.libs"

show_help() {
    cat <<EOF
Usage: ./build.sh <options>

    -m  <all>   : Compile all source code and package image
        <src> : Compile all options below. The following options can also be compiled separately
              - <lib>
                  <libmodsecurity>
              - <engine>
                  <openresty>
              - <web>
        <image>: package image
                  <wserver|wweb>
    -c          : use - c to specify the options that need to be cleaned up
    -h          : help
EOF
}

# 定义错误处理函数
handle_error() {
    local cmd=$1
    local ret=$2
    echo "Error occurred while executing '$cmd' with return code $ret"
    exit 1
}

# 定义执行命令并检查返回值的函数
execute_command() {
    local cmd=$1
    echo "Executing: $cmd"
    if ! eval "$cmd"; then
        handle_error "$cmd" $?
    fi
}

show_make_info() {
    printf "\033[0;33m******************************Do make $1**************************************\033[0m\n"
    return 0
}

make_openresty() {
    show_make_info openresty
    #compiling openresty
    local dbgpars=""
    if [[ $DEBUG_ON == 1 ]]; then
        dbgpars="-g3 -O0"
    fi

    # 如果编译动态libmodsecurity.so，使用--add-dynamic-module=${MODSECURITY_PATH}/modsecurity-nginx-v1.0.3
    # 如果编译静态libmodsecurity.a，使用--add-module=${MODSECURITY_PATH}/modsecurity-nginx-v1.0.3
    # 这里使用动态库
    cd $ENGINE_PATH
    local nginx_configure="./configure \\
        --prefix=$ENGINE_INSTALL/openresty \\
        --with-pcre-jit \\
        --with-http_v2_module \\
        --add-module=${TRD_PATH}/nginx_tcp_proxy_module \\
        --add-module=${TRD_PATH}/nginx-eval-module \\
        --add-module=${TRD_PATH}/nginx-upstream-fair \\
        --add-module=${TRD_PATH}/ngx_cache_purge-2.3 \\
        --add-module=${TRD_PATH}/ngx_http_limit_traffic_ratefilter_module \\
        --add-module=${TRD_PATH}/ngx_http_upstream_check_module \\
        --add-module=${NEU_PATH}/ngx_http_neteye_security \\
        --add-module=${NEU_PATH}/ngx_http_dynamic_resolve \\
        --add-module=${NEU_PATH}/ngx_http_upstream_fastest \\
        --add-module=${NEU_PATH}/ngx_http_upstream_persistence \\
        --add-module=${NEU_PATH}/ngx_http_session \\
        --add-module=${NEU_PATH}/ngx_http_robot_mitigation \\
        --add-module=${NEU_PATH}/ngx_http_status_page \\
        --add-module=${NEU_PATH}/ngx_http_if_extend \\
        --add-module=${NEU_PATH}/ngx_http_cache_extend \\
        --add-module=${NEU_PATH}/ngx_http_cookie_poisoning \\
        --add-module=${NEU_PATH}/ngx_http_web_defacement \\
        --add-module=${NEU_PATH}/ngx_http_ip_blacklist \\
        --add-module=${NEU_PATH}/ngx_http_ip_behavior \\
        --add-module=${NEU_PATH}/ngx_http_whitelist \\
        --add-module=${NEU_PATH}/ngx_http_statistics \\
        --add-dynamic-module=${MODSECURITY_PATH}/modsecurity-nginx-v1.0.3 \\
        --with-ld-opt=\"-Wl,-rpath,/usr/local/waf/lib -lz\""
    
    if [[ $DEBUG_ON == 1 ]]; then
        nginx_configure="$nginx_configure --with-debug"
    fi

    if [[ $USE_ASAN == 1 ]]; then
        nginx_configure="$nginx_configure --with-debug  --with-cc=\"gcc -fsanitize=address\" --with-cc-opt=\"-O0 -fno-omit-frame-pointer\" "
    fi
    eval "$nginx_configure"
    execute_command "make"

    rm -rf $ENGINE_INSTALL/openresty && mkdir -p $ENGINE_INSTALL/openresty
    execute_command "make install"
    cd $SRC_PATH
}

make_clean_openresty() {
    show_make_info "clean openresty"
    cd ${ENGINE_PATH} && make clean
    cd ${SRC_PATH}
}

make_modsecurity() {
    show_make_info modsecurity
    cd $MODSECURITY_LIB_PATH
    ./build.sh
    # ./configure --prefix=/usr/local/waf/lib/modsecurity
    ./configure --with-pcre2
    execute_command "make"
    cd ${SRC_PATH}
}

make_clean_transforms() {
    show_make_info "clean transforms"
    cd $SRC_PATH/transforms && make clean
    cd ${SRC_PATH}
}

make_transforms() {
    show_make_info transforms
    cd $SRC_PATH/transforms
    execute_command "make"
    cd ${SRC_PATH}
}

make_clean_modsecurity() {
    show_make_info "clean modsecurity"
    cd ${MODSECURITY_PATH} && make clean
    cd ${SRC_PATH}
}

make_web(){
    show_make_info "make web"
}

make_clean_web(){
    show_make_info "clean web"
}

make_image(){
    show_make_info "package image"
    if [ -f "${SRC_PATH}/waf.tar" ]; then
        execute_command "rm -rf waf.tar"
    fi
    show_make_info "clean old files"
    execute_command "rm -rf $IMAGE_PATH/*"

    show_make_info "start package"
    mkdir -p $IMAGE_PATH/waf/lib/
    mkdir -p $IMAGE_PATH/waf/openresty/
    mkdir -p $IMAGE_PATH/waf/modsec/
    mkdir -p $IMAGE_PATH/waf/config
    mkdir -p $IMAGE_PATH/waf/website/{conf,cert}
    mkdir -p $IMAGE_PATH/OpenWAF/

    cp  -rf $ENGINE_INSTALL/openresty/* $IMAGE_PATH/waf/openresty/
    cp  -rf $MODSECURITY_PATH/modsec/* $IMAGE_PATH/waf/modsec/
    cp  -rf $SRC_PATH/rules/rules $IMAGE_PATH/waf/modsec/
    cp  -rf $SRC_PATH/OpenWAF/* $IMAGE_PATH/OpenWAF/
    cp  -rf $SRC_PATH/transforms/transforms.so $IMAGE_PATH/OpenWAF/resty/

    cd $IMAGE_PATH
    execute_command "tar -cf ${SRC_PATH}/waf.tar *"
    cd ${SRC_PATH}
}

make_image_clean() {
    show_make_info "clean image"
}

make_build() {
    if [[ $target == "all" ]]; then
        make_modsecurity
        make_transforms
        make_openresty
        make_web
    elif [[ $target == "lib" ]]; then
        make_modsecurity
        make_transforms
    elif [[ $target == "engine" ]]; then
        make_openresty
    elif [[ $target == "web" ]]; then
        make_web
    elif [[ $target == "image" ]]; then
        make_image
    fi
}

make_clean(){
    if [[ $target == "all" ]]; then
        make_clean_modsecurity
        make_clean_transforms
        make_clean_openresty
        make_clean_web
    elif [[ $target == "lib" ]]; then
        make_clean_modsecurity
        make_clean_transforms
    elif [[ $target == "engine" ]]; then
        make_clean_openresty
    elif [[ $target == "web" ]]; then
        make_clean_web
    elif [[ $target == "image" ]]; then
        make_image_clean
    fi
}

while getopts hm:c: opt; do
    case $opt in
    m)
        makeflag=1
        if [[ $OPTARG != "" ]]; then
            target=$OPTARG
        fi
        ;;
    c)
        cmode=1
        bmode=
        if [[$OPTARG != ""]]; then
            target=$OPTARG
        fi
        ;;
    h)
        show_help
        exit 2
        ;;
    esac
done

if [ ! -z "$bmode" ]; then
    make_build
fi

if [ ! -z "$cmode" ]; then
    make_clean
fi